#include <stdx/all.h>
#include <json/json.h>

#define WGOLD_TEST_MAIN() int main(int argc, char** argv){return CommonMainProcess(argc, argv);}
#define WGOLD_TEST_LOOP(__TIMES__) int main(int argc, char** argv){return CommonMainProcess(argc, argv, __TIMES__);}

#define ColorPrint(__COLOR__, __FMT__, ...)		\
SetConsoleTextColor(__COLOR__);					\
printf(__FMT__, __VA_ARGS__);					\
SetConsoleTextColor(eWHITE);					\

/*服务端口*/
extern int PORT;

/*交易代码*/
extern const char* CODE;

/*服务地址*/
extern const char* HOST;

/*生成请求报文*/
extern string GetMessage();

/*打印应答报文*/
extern int PrintResult(SmartBuffer rsp);

string& GetTermType()
{
    static string msgtype = "jd";
    
    return msgtype;
}

void SetTermType(const string& type)
{
    GetTermType() = type;
}

int& GetMessageType()
{
    static int msgtype = 0;
    
    return msgtype;
}

void SetMessageType(int type)
{
    GetMessageType() = type;
}

string& GetHeadSession()
{
    static string session;
    
    return session;
}

void SetHeadSession(const string& session)
{
    GetHeadSession() = session;
}

sp<Socket> GetSocket(const char* ip, int port, int timeout = 3)
{
	sp<Socket> sock = newsp<Socket>();

	sock->init();
	sock->connect(ip, port, timeout);
	
	if (sock->isClosed()) sock = NULL;

	return sock;
}

int SendMessage(sp<Socket> sock, const char* code, const char* msg, int len)
{
	string dest = stdx::gbkcode(msg);

	msg = dest.c_str();
	len = dest.length();

	string termtype = GetTermType() + "  ";
	SmartBuffer buffer(len + 89 + 76);
	int codelen = strlen(code);
	char* ptr = buffer.str();
	string tmp;
	
	if (codelen > 4)
	{
		tmp = stdx::str(len + 81 + 76);
	}
	else
	{
		tmp = stdx::str(len + 81);
	}
	
	memset(ptr, ' ', 81 + 76);
	tmp = stdx::fill(tmp.c_str(), 8, true, '0');
	memcpy(ptr, tmp.c_str(), 8);

	string session = GetHeadSession();
	session = stdx::fill(session, 16, false, ' ');
	
	tmp = stdx::str(time(NULL) % 100000000);
	tmp = stdx::fill(tmp.c_str(), 8, true, '0');
	memcpy(ptr + 8, tmp.c_str(), 8);
	memcpy(ptr + 16, "1", 1);
	if (codelen > 4)
	{
		memcpy(ptr + 17, code, codelen);
		memcpy(ptr + 33, ("1  1 appquery      BJ00000                         " + session + "                                                                #").c_str(), 68 + 64);
		memcpy(ptr + 101 + 64, msg, len);
		ptr[34] = termtype[0];
		ptr[35] = termtype[1];
	}
	else
	{
		memcpy(ptr + 17, code, 4);
		memcpy(ptr + 21, ("1  1 appquery      BJ00000                         " + session + "#").c_str(), 68);
		memcpy(ptr + 89, msg, len);
		ptr[22] = termtype[0];
		ptr[23] = termtype[1];
		buffer.truncate(len + 89);
	}

	int res = sock->write(buffer.str(), buffer.size());

	return res;
}

SmartBuffer RecvMessage(sp<Socket> sock, string& code, int ms = 10000)
{
	int sz = 0;
	char tmp[68] = {0};
	SmartBuffer buffer;
	
	sock->setRecvTimeout(ms);

	if (sock->read(tmp, sizeof(tmp)) == sizeof(tmp))
	{
		code = string(tmp + 17, tmp + 23);

		tmp[8] = 0;
		
		if ((sz = atoi(tmp) - 60) <= 0) return buffer;

		if (sock->read(buffer.malloc(sz), sz) < 0) buffer.free();
	}

	if (buffer.size() > 0)
	{
		SmartBuffer dest(buffer.size() * 4);
		string tmp = stdx::utfcode(buffer.str());

		if (tmp.length() > 0)
		{
			dest = tmp;

			return dest;
		}

		buffer.free();
	}

	return buffer;
}

int CommonMainProcess(int argc, char** argv)
{
	Process::Instance(argc, argv);

	string msg;
	string code;
	sp<Socket> sock;

	SetConsoleTextColor(eWHITE);

	if ((msg = GetMessage()).empty())
	{
		ColorPrint(eRED, "%s\n", "生成请求报文失败");

		return XG_ERROR;
	}

	if ((sock = GetSocket(HOST, PORT)).get() == NULL)
	{
		ColorPrint(eRED, "连接服务器[%s:%d]失败\n", HOST, PORT);

        return XG_NETERR;
	}

	if (SendMessage(sock, CODE, msg.c_str(), msg.length()) < 0)
	{
		ColorPrint(eRED, "%s\n", "发送请求消息失败");

		return XG_NETERR;
	}
	
	SmartBuffer buffer = RecvMessage(sock, code);
	if (buffer.isNull())
	{
		ColorPrint(eRED, "%s\n", "接收应答消息失败");

		return XG_NETERR;
	}

	return PrintResult(buffer);
}

int CommonMainProcess(int argc, char** argv, int times)
{
	while (times-- > 0) CommonMainProcess(argc, argv);

	return times;
}

